home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / lfsquickcheck / lfsquickcheck.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-03-12  |  31.6 KB  |  1,102 lines

  1. /* 
  2.  * lfsquickcheck.c --
  3.  *
  4.  *    The lfsquickcheck program - To a quick check of an LFS file system 
  5.  *    to make sure it    is consistent.
  6.  *
  7.  * Copyright 1989 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /user2/mendel/lfs/src/cmds/checkLfs/RCS/checkLfs.c,v 1.1 90/06/01 10:10:18 mendel Exp Locker: mendel $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #ifdef __STDC__
  22. #define _HAS_PROTOTYPES
  23. #endif
  24.  
  25. #include <cfuncproto.h>
  26. #ifdef _HAS_PROTOTYPES
  27. #include <varargs.h>
  28. #endif
  29. #include <sprite.h>
  30. #include <stdio.h>
  31. #include <sys/types.h>
  32. #include <option.h>
  33. #include <stdlib.h>
  34. #include <string.h>
  35. #include <sys/file.h>
  36. #include <alloca.h>
  37. #include <bstring.h>
  38. #include <unistd.h>
  39. #include <bit.h>
  40. #include <time.h>
  41. #include <sys/time.h>
  42. #include <fs.h>
  43. #include <kernel/fs.h>
  44. #include <kernel/dev.h>
  45. #include <kernel/fsdm.h>
  46. #include <kernel/fslcl.h>
  47. #include <kernel/devDiskLabel.h>
  48.  
  49. #include <kernel/lfsDesc.h>
  50. #include <kernel/lfsDescMap.h>
  51. #include <kernel/lfsFileLayout.h>
  52. #include <kernel/lfsDirOpLog.h>
  53. #include <kernel/lfsSegLayout.h>
  54. #include <kernel/lfsStableMem.h>
  55. #include <kernel/lfsSuperBlock.h>
  56. #include <kernel/lfsUsageArray.h>
  57. #include <kernel/lfsStats.h>
  58.  
  59. #include "fscheck.h"
  60.  
  61.  
  62. /*
  63.  * The super block of the file system.
  64.  */
  65. LfsSuperBlock    *superBlockPtr;
  66.  
  67. /*
  68.  * The descriptor map and segment usage array of file system.
  69.  */
  70. ClientData descMapDataPtr;        /* Descriptor map of file system. */
  71. LfsDescMapCheckPoint *descMapCheckPointPtr; /* Most current descriptor map 
  72.                          * check point. */
  73. FdInfo        *descInfoArray;
  74.  
  75. ClientData   usageArrayDataPtr;    /* Data of usage map. */
  76.  
  77.  
  78. struct    ActiveDesc {
  79.     int    fileNumber;
  80.     LfsDescMapEntry *descMapPtr;
  81. } *activeDesc;
  82.  
  83. int        numBlocks;      /* Number of blocks in fs. */
  84.  
  85.  
  86. int    minorErrors;
  87. int    majorErrors;
  88.  
  89. /*
  90.  * Arguments.
  91.  */
  92. int    blockSize = 512;    /* File system block size. */
  93. int    superBlockOffset = 64;    /* Offset of super block. */
  94. Boolean dumpFlag = FALSE;    /* Dump version description of file system. */
  95. Boolean showDirLog = FALSE;    /* Show the directory log. */
  96. Boolean    verboseFlag = FALSE;    /* Trace progress of program. */
  97. char    *deviceName;        /* Device to use. */
  98. Boolean    full = FALSE;
  99. Option optionArray[] = {
  100.     {OPT_DOC, (char *) NULL,  (char *) NULL,
  101.     "Check a LFS file system and report problems.\n Synopsis: \"checkLfs [switches] deviceName\"\n Command-line switches are:"},
  102.     {OPT_INT, "blockSize", (Address) &blockSize, 
  103.     "Block size of file system."},
  104.     {OPT_INT, "superBlockOffset", (Address) &superBlockOffset, 
  105.     "Offset into device of the superBlock."},
  106.     {OPT_TRUE, "dump", (Address) &dumpFlag, 
  107.     "Print out a description of file system."},
  108.     {OPT_TRUE, "showDirLog", (Address) &showDirLog, 
  109.     "Print out the directory operation log."},
  110.     {OPT_TRUE, "full", (Address) &full, 
  111.     "Full a full error analysis."},
  112.     {OPT_TRUE, "verbose", (Address) &verboseFlag, 
  113.     "Output progress messages during execution."},
  114. };
  115. /*
  116.  * Forward routine declartions.
  117.  */
  118. extern Boolean LoadUsageArray _ARGS_((int diskFd, int checkPointSize, 
  119.             char *checkPointPtr));
  120. extern Boolean LoadDescMap _ARGS_((int diskFd, int checkPointSize,
  121.             char *checkPointPtr));
  122. extern char *GetUsageState _ARGS_((LfsSegUsageEntry *entryPtr));
  123. static void CheckAllFiles _ARGS_((int diskFd));
  124. static void CheckFile _ARGS_((int diskFd, int fileNum,             
  125.             LfsFileDescriptor *descPtr));
  126. static void CheckIndirectBlock _ARGS_((int diskFd, int fileNum, 
  127.         LfsFileDescriptor *descPtr, int blockNum, int blockAddress));
  128. static void CheckBlock _ARGS_((int diskFd, int fileNum, 
  129.         LfsFileDescriptor *descPtr, int blockNum, int blockAddress));
  130. static void CheckUsageArray _ARGS_((int diskFd));
  131. static void CheckSummaryRegions _ARGS_((int diskFd));
  132. static char *GetOwner _ARGS_((int blockNum));
  133. static void PrintSuperBlock _ARGS_((LfsSuperBlock *superBlockPtr));
  134. static void PrintCheckPointHdr _ARGS_((LfsCheckPointHdr *headerPtr, int region));
  135. static ClientData LoadStableMem _ARGS_((int diskFd, LfsStableMemParams *smemParamsPtr, LfsStableMemCheckPoint *cpPtr));
  136. static int GetStableMemBlockIndex _ARGS_((ClientData clientData, int blockNum));
  137. static void ShowDirLogBlock _ARGS_((LfsDirOpLogBlockHdr *hdrPtr, int addr));
  138.  
  139. static char *FmtTime _ARGS_((void));
  140.  
  141. extern int open();
  142. extern void panic();
  143. extern int gettimeofday _ARGS_((struct timeval *tp, struct timezone *tzp));
  144.  
  145. /*
  146.  *----------------------------------------------------------------------
  147.  *
  148.  * main --
  149.  *
  150.  *    Main routine of checklfs - parse arguments and do the work.
  151.  *
  152.  * Results:
  153.  *    None.
  154.  *
  155.  * Side effects:
  156.  *    None.
  157.  *
  158.  *----------------------------------------------------------------------
  159.  */
  160.  
  161. int
  162. main(argc,argv)
  163.     int    argc;
  164.     char *argv[];
  165. {
  166.     int       diskFd, maxCheckPointSize;
  167.     LfsCheckPointHdr    checkPointHdr[2], *checkPointHdrPtr;
  168.     char        *checkPointPtr, *trailerPtr;
  169.     LfsCheckPointRegion *regionPtr;
  170.     LfsCheckPointTrailer *trailPtr;
  171.     int            choosenOne;
  172.  
  173.  
  174.  
  175.     argc = Opt_Parse(argc, argv, optionArray, Opt_Number(optionArray), 0);
  176.     if (argc != 2) { 
  177.          Opt_PrintUsage(argv[0], optionArray, Opt_Number(optionArray));
  178.      exit(EXIT_BAD_ARG);
  179.     } else {
  180.     deviceName = argv[1];
  181.     }
  182.     diskFd = open(deviceName, O_RDONLY, 0);
  183.     if (diskFd < 0) {
  184.     fprintf(stderr,"%s:", argv[0]);
  185.     perror(deviceName);
  186.     exit(EXIT_HARD_ERROR);
  187.     }
  188.     /*
  189.      * Fill in the super block header.
  190.      */
  191.     superBlockPtr = (LfsSuperBlock *) malloc(LFS_SUPER_BLOCK_SIZE);
  192.     if (DiskRead(diskFd, superBlockOffset, sizeof(LfsSuperBlock), 
  193.         (char *)superBlockPtr) != sizeof(LfsSuperBlock)) {
  194.     fprintf(stderr,"%s:Can't read superblock.\n", deviceName);
  195.     exit(EXIT_READ_FAILURE);
  196.  
  197.     }
  198.     if (superBlockPtr->hdr.magic != LFS_SUPER_BLOCK_MAGIC) {
  199.     fprintf(stderr,"%s:Bad magic number for filesystem\n", deviceName);
  200.     exit(EXIT_READ_FAILURE);
  201.     }
  202.     if (dumpFlag) {
  203.        PrintSuperBlock(superBlockPtr);
  204.     }
  205.  
  206.     /*
  207.      * Examine the two checkpoint areas to locate the checkpoint area with the
  208.      * newest timestamp.
  209.      */
  210.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[0],
  211.         sizeof(LfsCheckPointHdr), (char *) (checkPointHdr+0)) != 
  212.     sizeof(LfsCheckPointHdr)) {
  213.     fprintf(stderr,"%s:Can't read checkPointHeader 0.\n", deviceName);
  214.     exit(EXIT_READ_FAILURE);
  215.     }
  216.     if (dumpFlag) {
  217.     PrintCheckPointHdr(checkPointHdr, 0);
  218.     }
  219.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[1],
  220.         sizeof(LfsCheckPointHdr), (char *) (checkPointHdr+1))  != 
  221.     sizeof(LfsCheckPointHdr)) {
  222.     fprintf(stderr,"%s:Can't read checkPointHeader 1.\n", deviceName);
  223.     exit(EXIT_READ_FAILURE);
  224.     }
  225.     if (dumpFlag) {
  226.     PrintCheckPointHdr(checkPointHdr+1, 1);
  227.     }
  228.  
  229.     choosenOne = (checkPointHdr[0].timestamp<checkPointHdr[1].timestamp) ?
  230.                 1 : 0;
  231.  
  232.     maxCheckPointSize = superBlockPtr->hdr.maxCheckPointBlocks * 
  233.                 blockSize;
  234.     checkPointPtr = malloc(maxCheckPointSize);
  235.     if (verboseFlag) {
  236.     printf("%s:Read LFS checkpoint from %s\n", FmtTime(), deviceName);
  237.     }
  238.     if (DiskRead(diskFd, superBlockPtr->hdr.checkPointOffset[choosenOne],
  239.         maxCheckPointSize, checkPointPtr) != maxCheckPointSize) {
  240.     fprintf(stderr,"%s:Can't read checkPoint %d\n", deviceName, choosenOne);
  241.     exit(EXIT_READ_FAILURE);
  242.     }
  243.  
  244.  
  245.     checkPointHdrPtr = (LfsCheckPointHdr *) checkPointPtr;
  246.     trailerPtr = (checkPointPtr + checkPointHdrPtr->size - 
  247.                 sizeof(LfsCheckPointTrailer));
  248.     trailPtr = (LfsCheckPointTrailer *) trailerPtr;
  249.     if (trailPtr->timestamp != checkPointHdrPtr->timestamp) {
  250.     fprintf(stderr,"%s:Header timestamp %d doesn't match trailer timestamp %d\n", deviceName, checkPointHdrPtr->timestamp, trailPtr->timestamp);
  251.     minorErrors++;
  252.     }
  253.     if (dumpFlag) {
  254.     printf("Using checkpoint area %d with timestamp %d domain %d (%s)\n",
  255.         choosenOne, checkPointHdrPtr->timestamp, 
  256.         checkPointHdrPtr->domainNumber, checkPointHdrPtr->domainPrefix);
  257.     }
  258.  
  259.     checkPointPtr = checkPointPtr + sizeof(LfsCheckPointHdr);
  260.  
  261.     numBlocks = superBlockPtr->usageArray.numberSegments * 
  262.                 (superBlockPtr->usageArray.segmentSize/blockSize) +
  263.                 superBlockPtr->hdr.logStartOffset;
  264.     /*
  265.      * Load the LFS metadata from the last checkpoint.
  266.      */
  267.     while (checkPointPtr < trailerPtr) { 
  268.     regionPtr = (LfsCheckPointRegion *) checkPointPtr;
  269.     if (regionPtr->size == 0) {
  270.         break;
  271.     }
  272.     switch (regionPtr->type) {
  273.     case LFS_SEG_USAGE_MOD:
  274.         LoadUsageArray(diskFd, regionPtr->size - sizeof(*regionPtr),
  275.                 (char *) (regionPtr+1));
  276.         break;
  277.     case LFS_DESC_MAP_MOD:
  278.         LoadDescMap(diskFd, regionPtr->size - sizeof(*regionPtr),
  279.                 (char *) (regionPtr+1));
  280.         break;
  281.     case LFS_FILE_LAYOUT_MOD:
  282.         if (regionPtr->size != sizeof(*regionPtr)) {
  283.         minorErrors++;
  284.         fprintf(stderr,"%s:Bad size %d for FILE_LAYOUT checkpoint\n",
  285.                 deviceName,regionPtr->size);
  286.         }
  287.         break;
  288.     default: {
  289.         minorErrors++;
  290.         fprintf(stderr,"%s:Unknown region type %d of size %d\n",
  291.             deviceName,
  292.             regionPtr->type, regionPtr->size);
  293.         break;
  294.         }
  295.     }
  296.     checkPointPtr += regionPtr->size;
  297.     }
  298.  
  299.     if (verboseFlag) {
  300.     printf("%s:Checking files\n", FmtTime());
  301.     }
  302.     CheckAllFiles(diskFd);
  303.     if (verboseFlag) {
  304.     printf("%s:Reporting errors\n",FmtTime());
  305.     }
  306.     if (majorErrors + minorErrors > 0) {
  307.     printf("%s: %d major errors %d minor errors\n", deviceName, 
  308.         majorErrors, minorErrors);
  309.     if (majorErrors > 0) {
  310.         exit(EXIT_HARD_ERROR);
  311.     } 
  312.     }
  313.     exit(EXIT_OK);
  314.     return EXIT_OK;
  315. }
  316.  
  317. /*
  318.  *----------------------------------------------------------------------
  319.  *
  320.  * LoadUsageArray --
  321.  *
  322.  *    Load the segment usage array into memory.
  323.  *
  324.  * Results:
  325.  *    TRUE if array can be loaded. FALSE otherwise.
  326.  *
  327.  * Side effects:
  328.  *    None.
  329.  *
  330.  *----------------------------------------------------------------------
  331.  */
  332.  
  333. Boolean
  334. LoadUsageArray(diskFd, checkPointSize, checkPointPtr)
  335.     int    diskFd;        /* File descriptor of disk. */
  336.     int    checkPointSize; /* Size of the checkpoint region. */
  337.     char *checkPointPtr; /* The checkpoint region. */
  338. {
  339.     LfsSegUsageParams    *usagePtr;
  340.     LfsSegUsageCheckPoint    *cp;
  341.     LfsSegUsageEntry        *entryPtr;
  342.     LfsStableMemCheckPoint *cpPtr;
  343.     LfsStableMemParams  *smemParamsPtr;
  344.     int    i, numClean,  numDirty, numFull, freeBlocks;
  345.     Boolean ret = TRUE;
  346.  
  347.     usagePtr = &(superBlockPtr->usageArray);
  348.     smemParamsPtr = &(superBlockPtr->usageArray.stableMem);
  349.  
  350.     cp = (LfsSegUsageCheckPoint *) checkPointPtr;
  351.      cpPtr = (LfsStableMemCheckPoint *)
  352.             (checkPointPtr + sizeof(LfsSegUsageCheckPoint));
  353.  
  354.     if (dumpFlag) { 
  355.     printf("NumClean segments %d (%3.1f%%) NumDirty %d (%3.1f%%)\n",
  356.     cp->numClean, 
  357.     100.0*cp->numClean/(double)usagePtr->numberSegments,
  358.     cp->numDirty,
  359.     100.0*cp->numDirty/(double)usagePtr->numberSegments);
  360.  
  361.     printf("FreeBlocks %d (%3.1f%%) dirtyActiveBytes %d (%3.1f%%) currentSegment %d\n",
  362.     cp->freeBlocks, 
  363.     100.0*cp->freeBlocks/ (double) numBlocks,
  364.     cp->dirtyActiveBytes, 
  365.     100.0*cp->dirtyActiveBytes/(double)usagePtr->segmentSize,
  366.     cp->currentSegment);
  367.     }
  368.  
  369.     usageArrayDataPtr =  LoadStableMem(diskFd, smemParamsPtr, cpPtr);
  370.     entryPtr = (LfsSegUsageEntry *) UsageArrayEntry(cp->currentSegment);
  371.     entryPtr->activeBytes = cp->curSegActiveBytes;
  372.     if (entryPtr->activeBytes <= cp->dirtyActiveBytes) {
  373.     entryPtr->flags = LFS_SEG_USAGE_DIRTY;
  374.     }
  375.    if (dumpFlag) { 
  376.     for (i = 0; i < usagePtr->numberSegments; i++) {
  377.         entryPtr = (LfsSegUsageEntry *) UsageArrayEntry(i);
  378.         printf("SegNum %d activeBytes %d state %s\n", 
  379.             i, entryPtr->activeBytes,
  380.             GetUsageState(entryPtr));
  381.     }
  382.     }
  383.     freeBlocks = 0;
  384.     numClean = numDirty = numFull = 0;
  385.     for (i = 0; i < usagePtr->numberSegments; i++) {
  386.     int bytes;
  387.     entryPtr = (LfsSegUsageEntry *) UsageArrayEntry(i);
  388.     bytes =  ((entryPtr->flags & LFS_SEG_USAGE_CLEAN) ? 0 :
  389.                 entryPtr->activeBytes);
  390.     bytes = usagePtr->segmentSize - bytes;
  391.     freeBlocks += (bytes + blockSize - 1)/blockSize;
  392.     if (entryPtr->flags == LFS_SEG_USAGE_CLEAN) {
  393.         numClean++;
  394.     } else if (entryPtr->flags == LFS_SEG_USAGE_DIRTY) {
  395.         numDirty++;
  396.         if (entryPtr->activeBytes > cp->dirtyActiveBytes) {
  397.         minorErrors++;
  398.            fprintf(stderr, 
  399.        "%s:UsageArray: segment %d is marked dirty with activeBytes of %d\n",
  400.             deviceName,i, entryPtr->activeBytes);
  401.         }
  402.     } else if (entryPtr->flags == 0) {
  403.         numFull++;
  404.         if (entryPtr->activeBytes < cp->dirtyActiveBytes) {
  405.         minorErrors++;
  406.            fprintf(stderr, 
  407.        "%s:UsageArray: segment %d is marked full with activeBytes of %d\n",
  408.             deviceName,i, entryPtr->activeBytes);
  409.         }
  410.     } else {
  411.         numFull++;
  412.         minorErrors++;
  413.            fprintf(stderr, 
  414.            "%s:UsageArray: segment %d has unknown flags of 0x%x\n",
  415.             deviceName, i, entryPtr->flags);
  416.     }
  417.     if (entryPtr->flags != LFS_SEG_USAGE_CLEAN) {
  418.         if ((entryPtr->activeBytes < 0) ||
  419.         (entryPtr->activeBytes > usagePtr->segmentSize)) {
  420.            majorErrors++;
  421.            fprintf(stderr, 
  422.            "%s:UsageArray: segment %d has bad activeBytes of %d\n",
  423.                 deviceName, i, entryPtr->activeBytes);
  424.         }
  425.     }
  426.     }
  427.     if (numClean != cp->numClean) {
  428.     minorErrors++;
  429.     fprintf(stderr,"%s:UsageArray: Clean count wrong; is %d should be %d\n",
  430.             deviceName, cp->numClean, numClean);
  431.  
  432.     }
  433.     if (numDirty != cp->numDirty) {
  434.     minorErrors++;
  435.     fprintf(stderr,"%s:UsageArray: Dirty count wrong; is %d should be %d\n",
  436.             deviceName, cp->numDirty, numDirty);
  437.  
  438.     }
  439.     if (freeBlocks != cp->freeBlocks) {
  440.     minorErrors++;
  441.     fprintf(stderr,"%s:UsageArray: FreeBlocks wrong; is %d should be %d\n",
  442.             deviceName, cp->freeBlocks, freeBlocks);
  443.     }
  444.    return ret;
  445. }
  446.  
  447.  
  448. /*
  449.  *----------------------------------------------------------------------
  450.  *
  451.  * LoadDescMap --
  452.  *
  453.  *    Load the descriptor map array into memory.
  454.  *
  455.  * Results:
  456.  *    None.
  457.  *
  458.  * Side effects:
  459.  *    None.
  460.  *
  461.  *----------------------------------------------------------------------
  462.  */
  463. Boolean 
  464. LoadDescMap(diskFd, checkPointSize, checkPointPtr)
  465.     int    diskFd;        /* File descriptor of disk. */
  466.     int    checkPointSize; /* Size of the checkpoint region. */
  467.     char *checkPointPtr; /* The checkpoint region. */
  468. {
  469.     LfsDescMapParams    *descMapParamsPtr;
  470.     LfsDescMapEntry    *descMapPtr;
  471.     LfsDescMapCheckPoint    *cp;
  472.     int                i;
  473.     LfsStableMemCheckPoint *cpPtr;
  474.     int            numAlloced;
  475.     LfsStableMemParams  *smemParamsPtr;
  476.    Boolean         ret = TRUE;
  477.  
  478.     descMapParamsPtr = &(superBlockPtr->descMap);
  479.     smemParamsPtr = &(superBlockPtr->descMap.stableMem);
  480.  
  481.  
  482.     descMapCheckPointPtr = cp = (LfsDescMapCheckPoint *) checkPointPtr;
  483.  
  484.      cpPtr = (LfsStableMemCheckPoint *)
  485.             (checkPointPtr + sizeof(LfsDescMapCheckPoint));
  486.  
  487.     descMapDataPtr =  LoadStableMem(diskFd, smemParamsPtr, cpPtr);
  488.  
  489.     if (dumpFlag) { 
  490.     printf("DescMap num allocated: %d\n", cp->numAllocDesc);
  491.     for (i = 0; i < superBlockPtr->descMap.maxDesc; i++) {
  492.         descMapPtr = DescMapEntry(i);
  493.         if (descMapPtr->flags == LFS_DESC_MAP_ALLOCED) { 
  494.         printf("File %d at %d (seg %d) version %d flags %d\n", 
  495.                 i, descMapPtr->blockAddress, 
  496.                 descMapPtr->blockAddress/
  497.                 (superBlockPtr->usageArray.segmentSize/blockSize),
  498.                 descMapPtr->truncVersion,
  499.                 descMapPtr->flags);
  500.         }
  501.     }
  502.     }
  503.     activeDesc = (struct ActiveDesc *) 
  504.         malloc(descMapCheckPointPtr->numAllocDesc * 
  505.             sizeof(activeDesc[0]));
  506.     numAlloced = 0;
  507.     for (i = 0; i < descMapParamsPtr->maxDesc; i++) {
  508.     descMapPtr = DescMapEntry(i);
  509.     if (descMapPtr->flags == LFS_DESC_MAP_ALLOCED) {
  510.         if (numAlloced < descMapCheckPointPtr->numAllocDesc) { 
  511.         activeDesc[numAlloced].fileNumber = i;
  512.         activeDesc[numAlloced].descMapPtr = descMapPtr;
  513.         }
  514.         numAlloced++;
  515.     } else if (descMapPtr->flags != 0) {
  516.         minorErrors++;
  517.         fprintf(stderr,"%s:Unknowned desc map flags (0x%x) for file %d\n",
  518.             deviceName, descMapPtr->flags, i);
  519.     }
  520.  
  521.     }
  522.     if (numAlloced != descMapCheckPointPtr->numAllocDesc) {
  523.     majorErrors++;
  524.     fprintf(stderr, "%s:DescMap: Bad alloc count; is %d should be %d\n",
  525.             deviceName, numAlloced, descMapCheckPointPtr->numAllocDesc);
  526.     descMapCheckPointPtr->numAllocDesc = numAlloced;
  527.  
  528.     }
  529.     return ret;
  530.  
  531. }
  532.  
  533. char *
  534. GetUsageState(entryPtr)
  535.     LfsSegUsageEntry *entryPtr;
  536. {
  537.     if (entryPtr->flags & LFS_SEG_USAGE_DIRTY) 
  538.     return "Dirty";
  539.     if (entryPtr->flags & LFS_SEG_USAGE_CLEAN) 
  540.     return "Clean";
  541.     return "Full";
  542. }
  543.  
  544. /*
  545.  *----------------------------------------------------------------------
  546.  *
  547.  * DiskRead --
  548.  *
  549.  *    Read data from disk.
  550.  *
  551.  * Results:
  552.  *    The number of bytes returned.  -1 if error.
  553.  *
  554.  * Side effects:
  555.  *    None.
  556.  *
  557.  *----------------------------------------------------------------------
  558.  */
  559. int
  560. DiskRead(diskFd, blockOffset, bufferSize, bufferPtr)
  561.     int    diskFd;        /* File descriptor of disk. */
  562.     int    blockOffset;    /* Block offset to start read. */
  563.     char *bufferPtr;    /* Buffer to place data. */
  564.     int     bufferSize;    /* Size of buffer. */
  565. {
  566.     int    status;
  567.     int    blocks;
  568.     char *bufPtr;
  569.  
  570.  
  571.     /*
  572.      * Seek to the start of the blocks to read.
  573.      */
  574.     status = lseek(diskFd, blockOffset*blockSize, L_SET);
  575.     if (status < 0) {
  576.     fprintf(stderr,"%s:", deviceName);
  577.     perror("lseek");
  578.     return status;
  579.     }
  580.     /*
  581.      * Read the blocks handling the case the a request that is not a 
  582.      * multiple number of blocks by reading to a temp buffer and copying.
  583.      */
  584.     blocks = (bufferSize + blockSize-1)/blockSize;
  585.     if (bufferSize != blocks * blockSize) { 
  586.     bufPtr = malloc(blocks*blockSize);
  587.     } else {
  588.     bufPtr = bufferPtr;
  589.     }
  590.     status = read(diskFd, bufPtr, blocks*blockSize);
  591.     if (status != blocks*blockSize) {
  592.     if (status < 0) {
  593.         fprintf(stderr,"%s:", deviceName);
  594.         perror("read device");
  595.         return status;
  596.     }
  597.     fprintf(stderr,"%s:Short read on device %d != %d\n",deviceName,
  598.         status, blocks*blockSize);
  599.     } else {
  600.     status = bufferSize;
  601.     }
  602.     if (bufPtr != bufferPtr) { 
  603.     bcopy(bufPtr, bufferPtr, bufferSize);
  604.     free(bufPtr);
  605.     }
  606.     return status;
  607. }
  608.  
  609. typedef struct StableMem {
  610.     LfsStableMemParams  *paramsPtr;  /* Parameters of stable memory. */
  611.     LfsStableMemCheckPoint *checkpointPtr;  /* Checkpoint pointer. */
  612.     char        *dataPtr;
  613. } StableMem;
  614.  
  615. /*
  616.  *----------------------------------------------------------------------
  617.  *
  618.  * LoadStableMem --
  619.  *
  620.  *    Load a stable memory data structure
  621.  *
  622.  * Results:
  623.  *    A clientdata that can be used to access stable mem.
  624.  *
  625.  * Side effects:
  626.  *    None.
  627.  *
  628.  *----------------------------------------------------------------------
  629.  */
  630. static ClientData 
  631. LoadStableMem(diskFd, smemParamsPtr, cpPtr)
  632.     int diskFd;    /* Disk of file system. */
  633.     LfsStableMemParams  *smemParamsPtr;  /* Parameters of stable memory. */
  634.     LfsStableMemCheckPoint *cpPtr;  /* Checkpoint pointer. */
  635. {
  636.     int arraySize;
  637.     char *startDataPtr, *dataPtr;
  638.     int *blockIndexPtr;
  639.     int blockNum;
  640.     LfsStableMemBlockHdr *hdrPtr;
  641.     StableMem *stableMemPtr;
  642.  
  643.     arraySize = smemParamsPtr->blockSize * smemParamsPtr->maxNumBlocks;
  644.     dataPtr = startDataPtr = malloc(arraySize);
  645.     blockIndexPtr = (int *)(((char *) cpPtr) + sizeof(LfsStableMemCheckPoint));
  646.     for (blockNum = 0; blockNum < cpPtr->numBlocks; blockNum++) {
  647.     unsigned int blockIndex = blockIndexPtr[blockNum];
  648.     if (blockIndex == FSDM_NIL_INDEX) {
  649.         bzero(dataPtr, smemParamsPtr->blockSize);
  650.     } else {
  651.         if (blockIndex+smemParamsPtr->blockSize/blockSize > numBlocks) {
  652.            majorErrors++;
  653.            fprintf(stderr, "%s:StableMem%d:Block %d out of range %d\n",
  654.                 deviceName, smemParamsPtr->memType, 
  655.                 blockNum, blockIndex);
  656.         blockIndex = 0;
  657.         }
  658.         if (DiskRead(diskFd, blockIndex, 
  659.                   smemParamsPtr->blockSize, dataPtr) != 
  660.         smemParamsPtr->blockSize) { 
  661.         majorErrors++;
  662.         fprintf(stderr, "%s:Can't read desc map block %d\n", deviceName, blockNum);
  663.         }
  664.         hdrPtr = (LfsStableMemBlockHdr *) dataPtr;
  665.         if ((hdrPtr->magic != LFS_STABLE_MEM_BLOCK_MAGIC) || 
  666.             (hdrPtr->memType != smemParamsPtr->memType) ||
  667.         (hdrPtr->blockNum != blockNum)) {
  668.         majorErrors++;
  669.         fprintf(stderr, "%s:Bad stable mem header for memType %d blockNum %d\n"
  670.                 , deviceName, smemParamsPtr->memType, blockNum);
  671.         }
  672.     }
  673.     dataPtr += smemParamsPtr->blockSize;
  674.     }
  675.     bzero(dataPtr, (smemParamsPtr->maxNumBlocks - cpPtr->numBlocks) * 
  676.             smemParamsPtr->blockSize);
  677.     stableMemPtr = (StableMem *) malloc(sizeof(StableMem));
  678.     stableMemPtr->paramsPtr = smemParamsPtr;
  679.     stableMemPtr->checkpointPtr = cpPtr;
  680.     stableMemPtr->dataPtr = startDataPtr;
  681.     return (ClientData) stableMemPtr;
  682. }
  683. char *
  684. GetStableMemEntry(clientData, entryNumber)
  685.     ClientData clientData;
  686.     int entryNumber;
  687. {
  688.     StableMem *stableMemPtr = (StableMem *) clientData;
  689.     int blockNum, offset;
  690.  
  691.     if ((entryNumber < 0) || 
  692.     (entryNumber >= stableMemPtr->paramsPtr->maxNumEntries)) {
  693.     fprintf(stderr,"Bad stable memory entry number %d\n", entryNumber);
  694.     entryNumber = 0;
  695.     }
  696.     blockNum = entryNumber / stableMemPtr->paramsPtr->entriesPerBlock;
  697.     offset = (entryNumber % stableMemPtr->paramsPtr->entriesPerBlock) * 
  698.         stableMemPtr->paramsPtr->entrySize + 
  699.            sizeof(LfsStableMemBlockHdr);
  700.  
  701.     return stableMemPtr->dataPtr + 
  702.         blockNum * stableMemPtr->paramsPtr-> blockSize + offset;
  703. }
  704. static int
  705. GetStableMemBlockIndex(clientData, blockNum)
  706.     ClientData clientData;
  707.     int blockNum;
  708. {
  709.     StableMem *stableMemPtr = (StableMem *) clientData;
  710.     int *blockIndexPtr;
  711.  
  712.     if ((blockNum < 0) || 
  713.     (blockNum >= stableMemPtr->paramsPtr->maxNumBlocks)) {
  714.     fprintf(stderr,"Bad stable memory block num %d\n", blockNum);
  715.     return FSDM_NIL_INDEX;
  716.     }
  717.     blockIndexPtr = (int *)((char *) (stableMemPtr->checkpointPtr) + sizeof(LfsStableMemCheckPoint));
  718.     return blockIndexPtr[blockNum];
  719. }
  720. int comparProc(aPtr, bPtr)
  721.     struct ActiveDesc *aPtr, *bPtr;
  722. {
  723.     return aPtr->descMapPtr->blockAddress - bPtr->descMapPtr->blockAddress;
  724. }
  725.  
  726. /*
  727.  *----------------------------------------------------------------------
  728.  *
  729.  * CheckAllFiles --
  730.  *
  731.  *    Check all the files in the system.
  732.  *
  733.  * Results:
  734.  *    None.
  735.  *
  736.  * Side effects:
  737.  *    None.
  738.  *
  739.  *----------------------------------------------------------------------
  740.  */
  741. static void
  742. CheckAllFiles(diskFd)
  743.     int diskFd;
  744. {
  745.     LfsFileDescriptor    *descPtr;
  746.     char *descBuf;
  747.     LfsDescMapEntry *descMapPtr;
  748.     int bufSize, i, j, d, segNum;
  749.     LfsSegUsageEntry        *entryPtr;
  750.  
  751.     int bufLoc;
  752.  
  753.     bufSize = superBlockPtr->fileLayout.descPerBlock * sizeof(*descPtr);
  754.  
  755.     descBuf = alloca(bufSize);
  756.     bufLoc = -1;
  757.  
  758.     descMapPtr = DescMapEntry(0);
  759.     if (descMapPtr->flags != LFS_DESC_MAP_ALLOCED) {
  760.     majorErrors++;
  761.     fprintf(stderr,"%s:CheckAllFiles: file 0 not allocated.\n",deviceName);
  762.     }
  763.     descMapPtr = DescMapEntry(1);
  764.     if (descMapPtr->flags != LFS_DESC_MAP_ALLOCED) {
  765.     majorErrors++;
  766.     fprintf(stderr,"%s:CheckAllFiles: file 1 not allocated.\n",deviceName);
  767.     }
  768.     printf("%s\n", FmtTime());
  769.     qsort((char *) activeDesc,  descMapCheckPointPtr->numAllocDesc,
  770.         sizeof(activeDesc[0]), comparProc);
  771.     printf("%s\n", FmtTime());
  772.  
  773.  
  774.     for (d = 0; d < descMapCheckPointPtr->numAllocDesc; d++) {
  775.         descMapPtr = activeDesc[d].descMapPtr;
  776.     i = activeDesc[d].fileNumber;
  777.     if ((descMapPtr->flags != LFS_DESC_MAP_ALLOCED) || (i < 3)) {
  778.         continue;
  779.     }
  780.     if ((descMapPtr->blockAddress < 0) || 
  781.         (descMapPtr->blockAddress > numBlocks)) {
  782.         majorErrors++;
  783.        fprintf(stderr, "%s:CheckAllFiles: Desc %d address out of range %d\n",
  784.             deviceName, i, descMapPtr->blockAddress);
  785.         continue;
  786.     }
  787.     if (bufLoc != descMapPtr->blockAddress) { 
  788.         if (DiskRead(diskFd, descMapPtr->blockAddress, bufSize, descBuf)
  789.                 != bufSize) {
  790.         majorErrors++;
  791.         fprintf(stderr,"%s:CheckAllFiles: Can't read desc for file %d\n",
  792.                     deviceName,i);
  793.         }
  794.         bufLoc = descMapPtr->blockAddress;
  795.     }
  796.     segNum = BlockToSegmentNum(descMapPtr->blockAddress);
  797.     entryPtr = (LfsSegUsageEntry *) UsageArrayEntry(segNum);
  798.     if (entryPtr->flags & LFS_SEG_USAGE_CLEAN) {
  799.         majorErrors++;
  800.        fprintf(stderr, "%s:CheckAllFiles: Desc %d address in clean segment %d (%d)\n",
  801.             deviceName, i, segNum, descMapPtr->blockAddress);
  802.     }
  803.     descPtr = (LfsFileDescriptor *)descBuf;
  804.     for (j = 0; j < superBlockPtr->fileLayout.descPerBlock; j++) {
  805.         if (!(descPtr->common.flags & FSDM_FD_ALLOC)) {
  806.         break;
  807.         }
  808.         if (descPtr->common.magic != FSDM_FD_MAGIC) {
  809.         majorErrors++;
  810.         fprintf(stderr,"%s:CheckAllFiles: Corrupted descriptor block at %d, magic number 0x%x\n", deviceName, descMapPtr->blockAddress, descPtr->common.magic);
  811.         }
  812.         if (descPtr->fileNumber == i) {
  813.         break;
  814.         }
  815.         descPtr++;
  816.     }
  817.     if ((j >= superBlockPtr->fileLayout.descPerBlock) ||
  818.         !(descPtr->common.flags & FSDM_FD_ALLOC) ||
  819.         (descPtr->fileNumber != i)) {
  820.         majorErrors++;
  821.         fprintf(stderr,"%s:CheckAllFiles: Can't desc for file %d at %d\n",
  822.             deviceName,i, descMapPtr->blockAddress);
  823.         continue;
  824.     } 
  825.     if (descPtr->common.fileType == FS_DIRECTORY) {
  826.     }
  827.     CheckFile(diskFd, i, descPtr);
  828.     }
  829. }
  830.  
  831. /*
  832.  *----------------------------------------------------------------------
  833.  *
  834.  * CheckFile --
  835.  *
  836.  *    Check a file in the system.
  837.  *
  838.  * Results:
  839.  *    None.
  840.  *
  841.  * Side effects:
  842.  *    None.
  843.  *
  844.  *----------------------------------------------------------------------
  845.  */
  846. static void
  847. CheckFile(diskFd, fileNum, descPtr) 
  848.     int diskFd;
  849.     int fileNum;
  850.     LfsFileDescriptor *descPtr;
  851. {
  852.  
  853. }
  854.  
  855.  
  856. /*
  857.  *----------------------------------------------------------------------
  858.  *
  859.  * CheckIndirectBlock --
  860.  *
  861.  *    Check an indirect block of a file..
  862.  *
  863.  * Results:
  864.  *    None.
  865.  *
  866.  * Side effects:
  867.  *    None.
  868.  *
  869.  *----------------------------------------------------------------------
  870.  */
  871.  
  872. static void
  873. CheckIndirectBlock(diskFd, fileNum, descPtr, blockNum, blockAddress)
  874.     int diskFd;
  875.     int fileNum;
  876.     LfsFileDescriptor *descPtr;
  877.     int blockNum;
  878.     int    blockAddress;
  879. {
  880.     int  i;
  881.     int blockPtrs[FS_BLOCK_SIZE/4];
  882.  
  883.     CheckBlock(diskFd, fileNum, descPtr, blockNum, blockAddress);
  884.     if (DiskRead(diskFd, blockAddress, FS_BLOCK_SIZE, (char *)blockPtrs)
  885.         != FS_BLOCK_SIZE) {
  886.     majorErrors++;
  887.     fprintf(stderr,"%s:CheckIndirectBlock: Can't read block %d of file %d.\n",
  888.                 deviceName, blockNum, fileNum);
  889.     return;
  890.  
  891.     }
  892.     if ((blockNum == -1) || (blockNum < -3)) { 
  893.     int start;
  894.     if (blockNum == -1) {
  895.         start = FSDM_NUM_DIRECT_BLOCKS;
  896.     } else {
  897.         start = FSDM_NUM_DIRECT_BLOCKS + (FS_BLOCK_SIZE/4) + 
  898.                  (FS_BLOCK_SIZE/4) * 
  899.                  (-blockNum - (FSDM_NUM_INDIRECT_BLOCKS+1));
  900.     }
  901.     for (i = 0; i < FS_BLOCK_SIZE/4; i++) {
  902.         if (blockPtrs[i] != FSDM_NIL_INDEX) { 
  903.         CheckBlock(diskFd, fileNum, descPtr,
  904.                start + i,blockPtrs[i]);
  905.         }
  906.     }
  907.     return;
  908.     } 
  909.     if (blockNum == -2) {
  910.     for (i = 0; i < FS_BLOCK_SIZE/4; i++) {
  911.         if (blockPtrs[i] != FSDM_NIL_INDEX) { 
  912.         CheckIndirectBlock(diskFd, fileNum, descPtr,
  913.                 - i  - (FSDM_NUM_INDIRECT_BLOCKS+1),blockPtrs[i]);
  914.         }
  915.     }
  916.     return;
  917.     }
  918.     majorErrors++;
  919.     fprintf(stderr,"%s:CheckIndirectBlock: Bad block number %d for file %d\n",
  920.             deviceName, blockNum, fileNum);
  921. }
  922.  
  923.  
  924. /*
  925.  *----------------------------------------------------------------------
  926.  *
  927.  * CheckFile --
  928.  *
  929.  *    Check a block of a file.
  930.  *
  931.  * Results:
  932.  *    None.
  933.  *
  934.  * Side effects:
  935.  *    None.
  936.  *
  937.  *----------------------------------------------------------------------
  938.  */
  939. static void
  940. CheckBlock(diskFd, fileNum, descPtr, blockNum, blockAddress)
  941.     int diskFd;
  942.     int fileNum;
  943.     LfsFileDescriptor *descPtr;
  944.     int blockNum;
  945.     int    blockAddress;
  946. {
  947. }
  948.  
  949. /*
  950.  *----------------------------------------------------------------------
  951.  *
  952.  * CheckUsageArray --
  953.  *
  954.  *    Check the segment usage array.
  955.  *
  956.  * Results:
  957.  *    None.
  958.  *
  959.  * Side effects:
  960.  *    None.
  961.  *
  962.  *----------------------------------------------------------------------
  963.  */
  964. static void
  965. CheckUsageArray(diskFd)
  966. int diskFd;
  967. {
  968. }
  969.  
  970. /*
  971.  *----------------------------------------------------------------------
  972.  *
  973.  * PrintSuperBlock --
  974.  *
  975.  *    Print super block contents.
  976.  *
  977.  * Results:
  978.  *    None.
  979.  *
  980.  * Side effects:
  981.  *    None.
  982.  *
  983.  *----------------------------------------------------------------------
  984.  */
  985. static void
  986. PrintSuperBlock(superBlockPtr)
  987.     LfsSuperBlock *superBlockPtr;
  988. {
  989.     printf("SuperBlock.hdr.version: %d\n", superBlockPtr->hdr.version);
  990.     printf("SuperBlock.hdr.blockSize: %d\n", 
  991.                 superBlockPtr->hdr.blockSize);
  992.     printf("SuperBlock.hdr.maxCheckPointBlocks: %d\n", 
  993.                 superBlockPtr->hdr.maxCheckPointBlocks);
  994.     printf("SuperBlock.hdr.checkPointOffset[0]: %d\n", 
  995.             superBlockPtr->hdr.checkPointOffset[0]);
  996.     printf("SuperBlock.hdr.checkPointOffset[1]: %d\n", 
  997.             superBlockPtr->hdr.checkPointOffset[1]);
  998.     printf("SuperBlock.hdr.logStartOffset: %d\n", 
  999.             superBlockPtr->hdr.logStartOffset);
  1000.     printf("SuperBlock.hdr.maxNumCacheBlocks: %d\n", 
  1001.             superBlockPtr->hdr.maxNumCacheBlocks);
  1002.     printf("SuperBlock.descMap.version: %d\n", superBlockPtr->descMap.version);
  1003.     printf("SuperBlock.descMap.maxDesc: %d\n", superBlockPtr->descMap.maxDesc);
  1004.     printf("SuperBlock.descMap.stableMem.blockSize: %d\n", 
  1005.             superBlockPtr->descMap.stableMem.blockSize);
  1006.     printf("SuperBlock.descMap.stableMem.maxNumBlocks: %d\n", 
  1007.             superBlockPtr->descMap.stableMem.maxNumBlocks);
  1008.     printf("SuperBlock.usageArray.segmentSize: %d\n", 
  1009.                 superBlockPtr->usageArray.segmentSize);
  1010.     printf("SuperBlock.usageArray.numberSegments: %d\n", 
  1011.                 superBlockPtr->usageArray.numberSegments);
  1012.     printf("SuperBlock.usageArray.minNumClean: %d\n", 
  1013.                 superBlockPtr->usageArray.minNumClean);
  1014.     printf("SuperBlock.usageArray.minFreeBlocks: %d\n", 
  1015.                 superBlockPtr->usageArray.minFreeBlocks);
  1016.     printf("SuperBlock.usageArray.stableMem.blockSize: %d\n", 
  1017.             superBlockPtr->descMap.stableMem.blockSize);
  1018.     printf("SuperBlock.usageArray.stableMem.maxNumBlocks: %d\n", 
  1019.             superBlockPtr->descMap.stableMem.maxNumBlocks);
  1020.     printf("SuperBlock.fileLayout.descPerBlock: %d\n", 
  1021.                 superBlockPtr->fileLayout.descPerBlock);
  1022. }
  1023.  
  1024.  
  1025. /*
  1026.  *----------------------------------------------------------------------
  1027.  *
  1028.  * PrintCheckPointHdr --
  1029.  *
  1030.  *    Print check point header contents.
  1031.  *
  1032.  * Results:
  1033.  *    None.
  1034.  *
  1035.  * Side effects:
  1036.  *    None.
  1037.  *
  1038.  *----------------------------------------------------------------------
  1039.  */
  1040. static void
  1041. PrintCheckPointHdr(headerPtr, region)
  1042.     LfsCheckPointHdr *headerPtr;
  1043.     int region;
  1044. {
  1045.     printf("CheckPointHdr[%d].timestamp: %d\n", region, headerPtr->timestamp);
  1046.     printf("CheckPointHdr[%d].size: %d\n", region, headerPtr->size);
  1047.     printf("CheckPointHdr[%d].version: %d\n", region, headerPtr->version);
  1048.     printf("CheckPointHdr[%d].domainPrefix: %s\n", region, 
  1049.                     headerPtr->domainPrefix);
  1050.     printf("CheckPointHdr[%d].domainNumber: %d\n", region,
  1051.                 headerPtr->domainNumber);
  1052.     printf("CheckPointHdr[%d].attachSeconds: %d\n", region, 
  1053.             headerPtr->attachSeconds);
  1054.     printf("CheckPointHdr[%d].detachSeconds: %d\n", region, 
  1055.             headerPtr->detachSeconds);
  1056.     printf("CheckPointHdr[%d].serverID: %d\n", region, 
  1057.             headerPtr->serverID);
  1058. }
  1059.  
  1060. static void
  1061. ShowDirLogBlock(hdrPtr, addr)
  1062.     LfsDirOpLogBlockHdr *hdrPtr;
  1063.     int addr;
  1064. {
  1065.     LfsDirOpLogEntry *entryPtr, *limitPtr;
  1066.  
  1067.     printf("Dirlog block at %d, size %d\n", addr, hdrPtr->size);
  1068.     limitPtr = (LfsDirOpLogEntry *) (((char *) hdrPtr) + hdrPtr->size);
  1069.     entryPtr = (LfsDirOpLogEntry *) (hdrPtr+1);
  1070.     while (entryPtr < limitPtr) {
  1071.     printf("LogSeqNum %d opFlags 0x%x dirFile %d dirOffset %d linkCount %d\n",
  1072.         entryPtr->hdr.logSeqNum, entryPtr->hdr.opFlags, 
  1073.         entryPtr->hdr.dirFileNumber,
  1074.         entryPtr->hdr.dirOffset, entryPtr->hdr.linkCount);
  1075.     entryPtr->dirEntry.fileName[entryPtr->dirEntry.nameLength] = '\0';
  1076.     printf("    File %d Name %s\n", entryPtr->dirEntry.fileNumber, 
  1077.         entryPtr->dirEntry.fileName);
  1078.     entryPtr = (LfsDirOpLogEntry *) 
  1079.              (((char *)entryPtr) + LFS_DIR_OP_LOG_ENTRY_SIZE(entryPtr));
  1080.     }
  1081.  
  1082. }
  1083.  
  1084. static char *
  1085. FmtTime()
  1086. {
  1087.      struct timeval tim;
  1088.      time_t  timeVal;
  1089.      static char timeBuffer[128];
  1090.  
  1091.      if (gettimeofday(&tim, (struct timezone *) NULL)) {
  1092.      perror("gettimeofday");
  1093.      return "Unknown";
  1094.      }
  1095.      timeVal = tim.tv_sec;
  1096.      (void)strcpy(timeBuffer, ctime(&timeVal) + sizeof("Sun Sep 16 ")-1);
  1097.  
  1098.      sprintf(timeBuffer+sizeof("01:03:52")-1,".%03d", tim.tv_usec/1000);
  1099.      return timeBuffer;
  1100. }
  1101.  
  1102.